﻿import type {RequestOptions} from '@@/plugin-request/request';
import type {RequestConfig} from '@umijs/max';
import {message, notification} from 'antd';
import {getUserInfo} from "@/common/user";
import {BaseResponse} from "@/services/family/api";
import {AxiosResponse} from "axios";

// 错误处理方案： 错误类型
enum ErrorShowType {
  SILENT = 0,
  WARN_MESSAGE = 1,
  ERROR_MESSAGE = 2,
  NOTIFICATION = 3,
  REDIRECT = 9,
}

// 与后端约定的响应数据格式
interface ResponseStructure {
  success: boolean;
  data: any;
  errorCode?: number;
  errorMessage?: string;
  showType?: ErrorShowType;
}

/**
 * @name 错误处理
 * pro 自带的错误处理， 可以在这里做自己的改动
 * @doc https://umijs.org/docs/max/request#配置
 */
export const errorConfig: RequestConfig<BaseResponse<any>> = {
  // 错误处理： umi@3 的错误处理方案。
  errorConfig: {
    // 错误抛出
    errorThrower: (res) => {
      const {code} = res as unknown as BaseResponse<any>;
      if ('0' !== code) {
        throw res; // 抛出自制的错误
      }

      // const { success, data, errorCode, errorMessage, showType } =
      //   res as unknown as ResponseStructure;
      // if (!success) {
      //   const error: any = new Error(errorMessage);
      //   error.name = 'BizError';
      //   error.info = { errorCode, errorMessage, showType, data };
      //   throw error; // 抛出自制的错误
      // }
    },
    // 错误接收及处理
    errorHandler: (error: any, opts: any) => {
      if(error.status === 200) {
        return;
      }
      console.error('请求失败', error, opts);
      if(error?.data?.code !== undefined) {
        return;
      }

      if (opts?.skipErrorHandler) throw error;
      // 我们的 errorThrower 抛出的错误。
      if (error.name === 'BizError') {
        const errorInfo: ResponseStructure | undefined = error.info;
        if (errorInfo) {
          const {errorMessage, errorCode} = errorInfo;
          switch (errorInfo.showType) {
            case ErrorShowType.SILENT:
              // do nothing
              break;
            case ErrorShowType.WARN_MESSAGE:
              message.warning(errorMessage);
              break;
            case ErrorShowType.ERROR_MESSAGE:
              message.error(errorMessage);
              break;
            case ErrorShowType.NOTIFICATION:
              notification.open({
                description: errorMessage,
                message: errorCode,
              });
              break;
            case ErrorShowType.REDIRECT:
              // TODO: redirect
              break;
            default:
              message.error(errorMessage);
          }
        }
      } else if (error.response) {
        // Axios 的错误
        // 请求成功发出且服务器也响应了状态码，但状态代码超出了 2xx 的范围
        message.error(`Response status:${error.response.status}`);
      } else if (error.request) {
        // 请求已经成功发起，但没有收到响应
        // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例，
        // 而在node.js中是 http.ClientRequest 的实例
        message.error('None response! Please retry.');
      } else {
        // 发送请求时出了点问题
        message.error('Request error, please retry.');
      }
    },
  },

  // 请求拦截器
  requestInterceptors: [
    (config: RequestOptions) => {
      // 拦截请求配置，进行个性化处理。
      const commonHeaders = {
        'Content-Type': 'application/json',
      };
      // 设置统一的授权请求头
      const userInfo = getUserInfo();
      if (userInfo) {
        commonHeaders['x-token'] = userInfo.token;
        commonHeaders['x-user-id'] = userInfo.id;
        if (userInfo.activeFamilyId && userInfo.activeFamilyId !== 0) {
          commonHeaders['x-family-id'] = userInfo.activeFamilyId;
        }
      }
      return {
        ...config,
        headers: commonHeaders,
      };
    },
  ],

  // 响应拦截器
  responseInterceptors: [(response) => {
    // 拦截响应数据，进行个性化处理
    const {data} = response;
    const {code, message: _message, result} = data as BaseResponse<any>;
    response.data = {
      ...data,
      data: result,
      success: '0' === code,
    };

    if ('0' !== code) {
      message.error('请求失败: ' + _message);
      throw response;
    }
    return response;
  },
  ],
};
